# 用SVM加灰度共生矩阵提取的特征，训练后对数据进行分类（神经网络前的数据预处理）
# 已证实可行（20X放大倍数下）

from skimage import feature
from sklearn.decomposition import PCA
from PIL import Image
from pylab import *
import os, shutil
from libsvm.python.svmutil import *
from src.preprocessing.feature.feature_extraction import *

# ......................................................................................
# HER2几种等级的路径
# 用训练集训练试一下，加起来2000张
HER2_g0_train_path = '../../../data/SVM_Classification/test/HER2_detection/train/g0/'
HER2_g1_train_path = '../../../data/SVM_Classification/test/HER2_detection/train/g1/'
HER2_g2_train_path = '../../../data/SVM_Classification/test/HER2_detection/train/g2/'
HER2_g3_train_path = '../../../data/SVM_Classification/test/HER2_detection/train/g3/'

# 用测试集测试一下
HER2_g0_test_path = '../../../data/SVM_Classification/test/HER2_detection/test/g0/'
HER2_g1_test_path = '../../../data/SVM_Classification/test/HER2_detection/test/g1/'
HER2_g2_test_path = '../../../data/SVM_Classification/test/HER2_detection/test/g2/'
HER2_g3_test_path = '../../../data/SVM_Classification/test/HER2_detection/test/g3/'

# 训练集特征保存的路径
path_lpa_train_g0 = '../../../data/SVM_Classification/test/feature_txt/glcm_data16_train_g0.txt'
path_lpa_train_g1 = '../../../data/SVM_Classification/test/feature_txt/glcm_data16_train_g1.txt'
path_lpa_train_g2 = '../../../data/SVM_Classification/test/feature_txt/glcm_data16_train_g2.txt'
path_lpa_train_g3 = '../../../data/SVM_Classification/test/feature_txt/glcm_data16_train_g3.txt'

# 测试集特征保存的路径
path_lpa_test_g0 = '../../../data/SVM_Classification/test/feature_txt/glcm_data16_test_g0.txt'
path_lpa_test_g1 = '../../../data/SVM_Classification/test/feature_txt/glcm_data16_test_g1.txt'
path_lpa_test_g2 = '../../../data/SVM_Classification/test/feature_txt/glcm_data16_test_g2.txt'
path_lpa_test_g3 = '../../../data/SVM_Classification/test/feature_txt/glcm_data16_test_g3.txt'

# 存在一起的图片的一个特征文件txt
path_lpa_train_all = '../../../data/SVM_Classification/test/feature_txt/glcm_data16_train_all.txt'
path_lpa_test_all = '../../../data/SVM_Classification/test/feature_txt/glcm_data16_test_all.txt'

# 处理的图片路径，符合要求的转移的图片存放路径与特征路径
classify_img_path = 'H:/临时存放地/her2_data/20x/g0_4710/'
transfer_img_path ='H:/临时存放地/test/transfer/20X/g0'
classify_img_feature_path = '../../../data/SVM_Classification/test/feature_txt/classify.txt'


# 满足四种等级的灰度共生矩阵特征文件生成（各自存为一个txt文件）
def create_glcm_txt(path_g0,path_g1,path_g2,path_g3,
                    path_lpa_g0, path_lpa_g1,path_lpa_g2,path_lpa_g3,
                    label_g0, label_g1, label_g2, label_g3):
    # g0特征
    glcm_feature_g0 = extract_glcm_feature(path_g0)
    # g1特征
    glcm_feature_g1 = extract_glcm_feature(path_g1)
    # g2特征
    glcm_feature_g2 = extract_glcm_feature(path_g2)
    # g3特征
    glcm_feature_g3 = extract_glcm_feature(path_g3)



    f0 = open(path_lpa_g0, 'w+')
    for j in range(0, len(glcm_feature_g0)):
        f0.write("%i "%label_g0)
        for i in range(0,len(glcm_feature_g0[0])):
            vec_temp = glcm_feature_g0[j]
            newcontext = "%i:"%(i + 1) + "%f"%(vec_temp[i]) + " "
            f0.write(newcontext)
        f0.write('\n')

    f1 = open(path_lpa_g1, 'w+')
    for j in range(0, len(glcm_feature_g1)):
        f1.write("%i "%label_g1)
        for i in range(0,len(glcm_feature_g1[0])):
            vec_temp = glcm_feature_g1[j]
            newcontext = "%i:"%(i + 1) + "%f"%(vec_temp[i]) + " "
            f1.write(newcontext)
        f1.write('\n')

    f2 = open(path_lpa_g2, 'w+')
    for j in range(0, len(glcm_feature_g2)):
        f2.write("%i "%label_g2)
        for i in range(0,len(glcm_feature_g2[0])):
            vec_temp = glcm_feature_g2[j]
            newcontext = "%i:"%(i + 1) + "%f"%(vec_temp[i]) + " "
            f2.write(newcontext)
        f2.write('\n')

    f3 = open(path_lpa_g3, 'w+')
    for j in range(0, len(glcm_feature_g3)):
        f3.write("%i "%label_g3)
        for i in range(0,len(glcm_feature_g3[0])):
            vec_temp = glcm_feature_g3[j]
            newcontext = "%i:"%(i + 1) + "%f"%(vec_temp[i]) + " "
            f3.write(newcontext)
        f3.write('\n')

# 满足四种等级的灰度共生矩阵特征文件生成（存为一个总的txt文件，用于训练）
def create_glcm_txt2(path_g0,path_g1,path_g2,path_g3,
                    path_lpa_all,
                    label_g0, label_g1, label_g2, label_g3):
    # g0特征
    glcm_feature_g0 = extract_glcm_feature(path_g0)
    # g1特征
    glcm_feature_g1 = extract_glcm_feature(path_g1)
    # g2特征
    glcm_feature_g2 = extract_glcm_feature(path_g2)
    # g3特征
    glcm_feature_g3 = extract_glcm_feature(path_g3)



    f_all = open(path_lpa_all, 'w+')
    for j in range(0, len(glcm_feature_g0)):
        f_all.write("%i "%label_g0)
        for i in range(0,len(glcm_feature_g0[0])):
            vec_temp = glcm_feature_g0[j]
            newcontext = "%i:"%(i + 1) + "%f"%(vec_temp[i]) + " "
            f_all.write(newcontext)
        f_all.write('\n')

    for j in range(0, len(glcm_feature_g1)):
        f_all.write("%i "%label_g1)
        for i in range(0,len(glcm_feature_g1[0])):
            vec_temp = glcm_feature_g1[j]
            newcontext = "%i:"%(i + 1) + "%f"%(vec_temp[i]) + " "
            f_all.write(newcontext)
        f_all.write('\n')

    for j in range(0, len(glcm_feature_g2)):
        f_all.write("%i "%label_g2)
        for i in range(0,len(glcm_feature_g2[0])):
            vec_temp = glcm_feature_g2[j]
            newcontext = "%i:"%(i + 1) + "%f"%(vec_temp[i]) + " "
            f_all.write(newcontext)
        f_all.write('\n')

    for j in range(0, len(glcm_feature_g3)):
        f_all.write("%i "%label_g3)
        for i in range(0,len(glcm_feature_g3[0])):
            vec_temp = glcm_feature_g3[j]
            newcontext = "%i:"%(i + 1) + "%f"%(vec_temp[i]) + " "
            f_all.write(newcontext)
        f_all.write('\n')

# 提取某一个文件夹内被大归类的图片数据集
def create_glcm_txt3(path_classify,
                    path_svm_classify,
                    label_classify):
    # 提取正样本的glcm特征
    glcm_feature_classify = extract_glcm_feature(path_classify)
    # 提取负样本的glcm特征
    # glcm_feature_n = extract_glcm_feature(path_negative)
    f1 = open(path_svm_classify, 'w+')
    for j in range(0, len(glcm_feature_classify)):
        f1.write("%i " % label_classify)
        for i in range(0, len(glcm_feature_classify[0])):
            vec_temp = glcm_feature_classify[j]
            newcontext = "%i:" % (i + 1) + "%f" % (vec_temp[i]) + " "
            f1.write(newcontext)
        f1.write('\n')



# 提取 glcm 特征,并将特征写入txt文件中
def extract_glcm_feature(path_image):
    # 存储所有样本的glcm特征
    feature_glcm_total = []
    for files in os.listdir(path_image):
        # 存储单张图片的glcm特征
        textural_feature = []
        # 以灰度模式读取图片
        image = array(Image.open(path_image + files).convert('L'))
        # 计算灰度共生矩阵
        glcm = feature.greycomatrix(image, [5], [0], 256, symmetric=True, normed=True)
        # 得到不同统计量
        textural_feature.append(feature.greycoprops(glcm, 'contrast')[0, 0])
        textural_feature.append(feature.greycoprops(glcm, 'dissimilarity')[0, 0])
        textural_feature.append(feature.greycoprops(glcm, 'homogeneity')[0, 0])
        textural_feature.append(feature.greycoprops(glcm, 'ASM')[0, 0])
        textural_feature.append(feature.greycoprops(glcm, 'energy')[0, 0])
        textural_feature.append(feature.greycoprops(glcm, 'correlation')[0, 0])
        # 每遍历一张图片，将该图片的特征向量拼接到下一行
        feature_glcm_total.append(textural_feature)
    # 归一化
    # textural_feature_nor = MaxMinNormalization(feature_glcm_total)
    return feature_glcm_total


if __name__ == '__main__':
    # HER2染色的切片提取特征（已提取）
    # 训练集提取特征为一个txt文件
    # create_glcm_txt2(HER2_g0_train_path,HER2_g1_train_path, HER2_g2_train_path, HER2_g3_train_path,
    #                 path_lpa_train_all,
    #                 1, 2, 3, 4)
    #
    # 训练集提取特征为各个txt文件
    # create_glcm_txt(HER2_g0_test_path,HER2_g1_test_path, HER2_g2_test_path, HER2_g3_test_path,
    #                 path_lpa_test_g0, path_lpa_test_g1, path_lpa_test_g2, path_lpa_test_g3,
    #                 1, 2, 3, 4)

    # 测试集提取特征为一个txt文件
    # create_glcm_txt2(HER2_g0_test_path,HER2_g1_test_path, HER2_g2_test_path, HER2_g3_test_path,
    #                  path_lpa_test_all,
    #                 1, 2, 3, 4)



    # 训练特征路径和测试特征路径
    train_path = path_lpa_train_all
    test_path = path_lpa_test_all

    #读入训练文件
    y, x = svm_read_problem(train_path)
    # 读入测试文件
    # y2, x2 = svm_read_problem(test_path)

    # 训练svm分类模型
    # m=svm_train(y,x,'-c 32768.0 -g 0.0001 -b 1')
    m = svm_train(y, x, '-c 32768.0 -g 0.0001 -b 0')

    # svm分类
    # p_lable, p_acc, p_val = svm_predict(y2, x2, m, options='-b 1')

    # p_lable, p_acc, p_val = svm_predict(y2, x2, m, options='-b 0')

# #..................................（实际图像处理）.......................................
# 测试集提取特征为一个txt文件
# 1234对应着g0,g1,g2,g3等级
kind = 1
create_glcm_txt3(classify_img_path,classify_img_feature_path,kind)


# 处理要预测文件夹中的图片
y2,x2 = svm_read_problem(classify_img_feature_path)
#输出单张图片预测情况
length=len(open(classify_img_feature_path,'rU').readlines())
print(length)
# k = 0
image_num = []  # 存储图片序号

for i in range(0,length,1):
    # p_lable, p_acc, p_val = svm_predict(y2[i:i + 1], x2[i:i + 1], m, options='-b 1')
    p_lable, p_acc, p_val = svm_predict(y2[i:i + 1], x2[i:i + 1], m, options='-b 0')
    if p_lable[0] == kind:
        image_num.append(i)

print(len(image_num))

file_num = 0

# shutil.copy('C:\\spam.txt', 'C:\\delicious')

for files in os.listdir(classify_img_path):
    # 将预测结果为normal的图片移动到normal文件夹
    if file_num in image_num:
        # os.remove(path_positive + files)
        # 这里是复制满足要求的图片到新的路径
        shutil.copy(classify_img_path + files,
                    transfer_img_path)

    file_num = file_num + 1

#............................................................................